using System;

namespace Google.Apps.Provisioning.Authentication
{
    /// <summary>
    /// Handles the management of a Google security token over its lifetime.  When Google issues a security
    /// token, that token is valid for the next 24 hours.  This class will automatically refresh the token if
    /// needed and insulate the caller from token management.  Note: once an instance of this class is created,
    /// that same instance needs to be re-used in order for the token management to work.  Once the instance
    /// goes out of scope, the fact that a token was retrieved is lost.
    /// This class is thread-safe.
    /// </summary>
    public class AuthenticationToken
    {
        private string email;
        private string password;
        private string sid;
        private DateTime tokenBirthDate;

        private object padLock = new object();

        public string Email
        {
            get { return email; }
        }

        public DateTime TokenBirthDate
        {
            get { return tokenBirthDate; }
        }

        public AuthenticationToken( string email, string password )
        {
            this.email          = email;
            this.password       = password;
            tokenBirthDate = DateTime.MinValue;

            RefreshSecurityToken();
        }

        public string GetSecurityToken()
        {
            RefreshSecurityToken();
            return sid;
        }

        private void RefreshSecurityToken()
        {
            // Google SID token lives for 24 hours.  We refresh after 23 to be safe.
            // This is locked in case multiple threads attempt to refresh the token concurrently
            // which would result in two different tokens being issued to consumers at almost the 
            // same time, but the second token issued would be invalid on Google's end.
            lock( padLock )
            {
                TimeSpan ts = DateTime.Now - tokenBirthDate;

                if ( ts.TotalHours >= 23 )
                {
                    sid = AuthenticationManager.GetSecurityToken( email, password );
                    tokenBirthDate = DateTime.Now;
                }
            }
        }

        public void Debug()
        {
            Console.Out.WriteLine( "SID=" + sid );
            Console.Out.WriteLine( "BirthDate=" + tokenBirthDate.ToLongDateString() );
        }
    }
}
